package fr.gdi.android.news.api.greader;

import java.io.IOException;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;

import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.HttpResponseException;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.util.GoogleHeaders;

import fr.gdi.android.news.api.AbstractLicensingActivity;

public abstract class AbstractGReaderActivity extends AbstractLicensingActivity
{
    
    private static final String AUTH_TOKEN_TYPE = "reader";
    private static final int REQUEST_AUTHENTICATE = 1;
    private static final int DIALOG_ACCOUNTS = 2;
    private String authToken;
    private static HttpTransport transport;

    public AbstractGReaderActivity()
    {
        transport = NetHttpTransport.create();
        GoogleHeaders headers = (GoogleHeaders) transport.defaultHeaders;
        headers.setApplicationName("fr.gdi.android.api/1.0");
        headers.gdataVersion = "2";
    }

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        checkAccess();
    }
    
    public void gotAccount(boolean tokenExpired)
    {
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
        String accountName = settings.getString("accountName", null);
        if (accountName != null)
        {
            AccountManager manager = AccountManager.get(this);
            Account[] accounts = manager.getAccountsByType("com.google");
            int size = accounts.length;
            for (int i = 0; i < size; i++)
            {
                Account account = accounts[i];
                if (accountName.equals(account.name))
                {
                    if (tokenExpired)
                    {
                        manager.invalidateAuthToken("com.google", this.authToken);
                    }
                    gotAccount(manager, account);
                    return;
                }
            }
        }
        showDialog(DIALOG_ACCOUNTS);
    }

    private void gotAccount(final AccountManager manager, final Account account)
    {
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString("accountName", account.name);
        editor.commit();
        new Thread() {
            
            @Override
            public void run()
            {
                try
                {
                    final Bundle bundle = manager.getAuthToken(account, AUTH_TOKEN_TYPE, true, null, null).getResult();
                    runOnUiThread(new Runnable() {
                        public void run()
                        {
                            try
                            {
                                if (bundle.containsKey(AccountManager.KEY_INTENT))
                                {
                                    Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);
                                    int flags = intent.getFlags();
                                    flags &= ~Intent.FLAG_ACTIVITY_NEW_TASK;
                                    intent.setFlags(flags);
                                    startActivityForResult(intent, REQUEST_AUTHENTICATE);
                                }
                                else if (bundle.containsKey(AccountManager.KEY_AUTHTOKEN))
                                {
                                    authenticatedClientLogin(bundle.getString(AccountManager.KEY_AUTHTOKEN), account.name);
                                }
                            }
                            catch (Exception e)
                            {
                                handleException(e);
                            }
                        }
                    });
                }
                catch (Exception e)
                {
                    handleException(e);
                }
            }
        }.start();
    }

    private void handleException(Exception e)
    {
        Log.e(this.getClass().getName(), e.getMessage(), e);
        if (e instanceof HttpResponseException)
        {
            HttpResponse response = ((HttpResponseException) e).response;
            int statusCode = response.statusCode;
            try
            {
                response.ignore();
            }
            catch (IOException e1)
            {
                e1.printStackTrace();
            }
            if (statusCode == 401 || statusCode == 403)
            {
                gotAccount(true);
                return;
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode)
        {
            case REQUEST_AUTHENTICATE:
                if (resultCode == RESULT_OK)
                {
                    gotAccount(false);
                }
                else
                {
                    showDialog(DIALOG_ACCOUNTS);
                }
                break;
        }
    }

    protected Dialog onCreateDialog(int id)
    {
        switch (id)
        {
            case DIALOG_ACCOUNTS:
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("Select a Google account");
                final AccountManager manager = AccountManager.get(this);
                final Account[] accounts = manager.getAccountsByType("com.google");
                final int size = accounts.length;
                String[] names = new String[size];
                for (int i = 0; i < size; i++)
                {
                    names[i] = accounts[i].name;
                }
                builder.setItems(names, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which)
                    {
                        gotAccount(manager, accounts[which]);
                    }
                });
                return builder.create();
        }
        return super.onCreateDialog(id);
    }

    private void authenticatedClientLogin(String authToken, String accountName)
    {
        this.authToken = authToken;
        ((GoogleHeaders) transport.defaultHeaders).setGoogleLogin(authToken);
        authenticated(accountName);
    }
 
    protected abstract void authenticated(String accountName);
}